package com.demo2do.boyle.common.entity.customer;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import com.alibaba.fastjson.annotation.JSONField;
import com.demo2do.boyle.common.entity.AuditStatus;
import com.demo2do.boyle.common.entity.customer.social.SocialAccount;
import com.demo2do.boyle.common.entity.customer.wallet.Wallet;
import com.demo2do.boyle.common.entity.geo.Geo;
import com.demo2do.core.utils.SignatureUtils;

/**
 * 
 * @author Wilson
 */
@Entity
@Table(name = "customer")
public class Customer {

    @Id
    @GeneratedValue
    private Integer id;

    /** 圈圈账号 */
    private String code;
    
    private String mobile;

    private String password;
    
    @Embedded
    private Profile profile;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @Fetch(FetchMode.SELECT)
    @PrimaryKeyJoinColumn
    @JSONField(serialize = false)
	private CustomerTag customerTag;
    
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @Fetch(FetchMode.SELECT)
    @PrimaryKeyJoinColumn
    @JSONField(serialize = false)
    private Wallet wallet;

    @OneToMany(mappedBy = "customer", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<SocialAccount> socialAccounts;
    
    /** 注册来源 */
    @Enumerated(EnumType.ORDINAL)
    private Source source;

    @Enumerated(EnumType.ORDINAL)
    private AuditStatus auditStatus;
    
    private Date createTime;

	@Column(name = "is_deleted")
    private boolean disabled; 

    private String openId;
    
    @Transient
    private List<Integer> advertisementIds = new ArrayList<Integer>();

    /**
     * default constructor
     */
    public Customer() {
    	
    }

    /**
     * The constructor using mobile as key
     * 
     * @param mobile
     */
    public Customer(String mobile) {
        this.mobile = mobile;
    }
    
    /**
     * The constructor using mobile and source
     * 
     * @param mobile
     * @param source
     */
    public Customer(String mobile, Source source) {
    	this.source = source;
    	this.mobile = mobile;
    }

    /**
     * Initialize customer basic fields
     * 
     * @param source
     * @param code
     * @param customerTag
     * @param wallet
     * @return
     */
    public Customer initialize(Source source, String code, CustomerTag customerTag, Wallet wallet) {

    	this.source = source;
    	
        // using mobile's last 6 digitals as password 
        this.password = SignatureUtils.makeMD5Signature(this.mobile.substring(this.mobile.length()-6));

        this.code = code;
        
        this.auditStatus = AuditStatus.AUDITING;
        this.createTime = new Date();
        
        this.customerTag = customerTag;
        this.wallet = wallet;
        
        this.disabled = false;
        
        return this;
    }
    
    /**
     * Update customer
     * 
     * @param age
     * @param sex
     * @param city
     * @param province
     * @param customerTag
     * @return
     */
    public Customer update(Integer age, Sex sex, Geo city, Geo province) {
    	this.profile.setAge(age);
    	this.profile.setSex(sex);
    	this.profile.setCity(city);
    	this.profile.setSex(sex);
    	return this;
    }
    
    /**
     * bind openid
     * @param openId
     * @return
     */
    public Customer bindOpenId(String openId) {
        this.openId = openId;
        return this;
    }
    
    /**
     * unBind openid
     * @return
     */
    public Customer unBindOpenId() {
        this.openId = null;
        return this;
    }
    
    /**
     * audit customer to audited
     * @return
     */
    public Customer audit() {
        this.auditStatus = AuditStatus.AUDITED;
        return this;
    }

    /**
     * update password
     * 
     * @param password
     * @return
     */
    public Customer password(String password) {
        this.password = password;
        return this;
    }

	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}

	/**
	 * @return the code
	 */
	public String getCode() {
		return code;
	}

	/**
	 * @return the mobile
	 */
	public String getMobile() {
		return mobile;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @return the profile
	 */
	public Profile getProfile() {
		return profile;
	}

	/**
	 * @return the customerTag
	 */
	public CustomerTag getCustomerTag() {
		return customerTag;
	}
	
	/**
	 * @return the wallet
	 */
	public Wallet getWallet() {
		return this.wallet;
	}
	
	/**
	 * @return the socialAccounts
	 */
	public List<SocialAccount> getSocialAccounts() {
		return this.socialAccounts;
	}
	
	/**
	 * @return the source
	 */
	public Source getSource() {
		return source;
	}

	/**
	 * @return the auditStatus
	 */
	public AuditStatus getAuditStatus() {
		return auditStatus;
	}

	/**
	 * @return the createTime
	 */
	public Date getCreateTime() {
		return createTime;
	}

	/**
	 * @return the disabled
	 */
	public boolean isDisabled() {
		return disabled;
	}

	/**
     * @return the openId
     */
    public String getOpenId() {
        return openId;
    }

    /**
     * @param openId the openId to set
     */
    public void setOpenId(String openId) {
        this.openId = openId;
    }

    /**
	 * @param id the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}

	/**
	 * @param code the code to set
	 */
	public void setCode(String code) {
		this.code = code;
	}

	/**
	 * @param mobile the mobile to set
	 */
	public void setMobile(String mobile) {
		this.mobile = mobile;
	}

	/**
	 * @param password the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * @param profile the profile to set
	 */
	public void setProfile(Profile profile) {
		this.profile = profile;
	}

	/**
	 * @param customerTag the customerTag to set
	 */
	public void setCustomerTag(CustomerTag customerTag) {
		this.customerTag = customerTag;
	}
	
	/**
	 * @param wallet the wallet to set
	 */
	public void setWallet(Wallet wallet) {
		this.wallet = wallet;
	}
	
	/**
	 * @param socialAccounts the socialAccounts to set
	 */
	public void setSocialAccounts(List<SocialAccount> socialAccounts) {
		this.socialAccounts = socialAccounts;
	}
	
	/**
	 * @param source the source to set
	 */
	public void setSource(Source source) {
		this.source = source;
	}

	/**
	 * @param auditStatus the auditStatus to set
	 */
	public void setAuditStatus(AuditStatus auditStatus) {
		this.auditStatus = auditStatus;
	}

	/**
	 * @param createTime the createTime to set
	 */
	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	/**
	 * @param disabled the disabled to set
	 */
	public void setDisabled(boolean disabled) {
		this.disabled = disabled;
	}

	public List<Integer> getAdvertisementIds() {
		return advertisementIds;
	}

	public void setAdvertisementIds(List<Integer> advertisementIds) {
		this.advertisementIds = advertisementIds;
	}
	
    public boolean getAutitingSocialAccount(){
    	boolean result = true;
    	for (SocialAccount socialAccount : socialAccounts) {
    		if (socialAccount.getAuditStatus() == AuditStatus.AUDITING) {
    			result = false;
    			break;
			}
		}
    	
		return result;
    }
}
